package io.dshubs.archives.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.dshubs.archives.dao.*;
import io.dshubs.archives.entity.*;
import io.dshubs.archives.entity.vo.ArchiveWarehouseVo;
import io.dshubs.archives.service.ArchiveWarehouseLocationService;
import io.dshubs.archives.service.ArchiveWarehouseService;
import io.dshubs.archives.service.ArchiveWarehouseZoneService;
import io.dshubs.commons.mybatis.enums.DelFlagEnum;
import io.dshubs.commons.mybatis.service.impl.BaseServiceImpl;
import io.dshubs.commons.security.context.TenantContext;
import io.dshubs.commons.security.user.SecurityUser;
import io.dshubs.commons.security.user.UserDetail;
import io.dshubs.commons.tools.constant.Constant;
import io.dshubs.commons.tools.enums.SuperAdminEnum;
import io.dshubs.commons.tools.exception.RenException;
import io.dshubs.commons.tools.page.PageData;
import io.dshubs.commons.tools.utils.ConvertUtils;
import io.dshubs.dto.SysDictTypeDTO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.NumberFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 库房表 服务实现类
 * </p>
 *
 * @author tan
 * @since 2021-08-17
 */
@Service
public class ArchiveWarehouseServiceImpl extends BaseServiceImpl<ArchiveWarehouseMapper, ArchiveWarehouse> implements ArchiveWarehouseService {

    @Autowired
    private ArchiveWarehouseZoneService archiveWarehouseZoneService;

    @Autowired
    private ArchiveWarehouseZoneMapper archiveWarehouseZoneMapper;

    @Autowired
    private ArchiveWarehouseLocationService archiveWarehouseLocationService;

    @Autowired
    private ArchiveWarehouseLocationMapper archiveWarehouseLocationMapper;

    @Autowired
    private ArchiveBaseStoreMapper archiveBaseStoreMapper;

    @Autowired
    private ArchiveBaseInfoMapper archiveBaseInfoMapper;

    @Override
    public PageData<ArchiveWarehouse> page(Map<String, Object> params) {
        IPage<ArchiveWarehouse> page = baseDao.selectPage(
                getPage(params, Constant.CREATE_DATE, false),
                getWrapper(params)
        );

        return getPageData(page, ArchiveWarehouse.class);
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void deleteBatch(List<Long> ids) {
        List<ArchiveWarehouseZone> zoneList = archiveWarehouseZoneMapper.selectList(new QueryWrapper<ArchiveWarehouseZone>().eq("warehouse_id", ids));
        if(CollectionUtils.isNotEmpty(zoneList)) {
            archiveWarehouseZoneService.deleteBatch(zoneList.stream().map(ArchiveWarehouseZone::getId).collect(Collectors.toList()));
        }
        this.baseDao.deleteBatchIds(ids);
    }

    private QueryWrapper<ArchiveWarehouse> getWrapper(Map<String, Object> params){
        String name = (String)params.get("name");
        String code = (String)params.get("code");
        String warehouseId = (String)params.get("warehouseId");
        QueryWrapper<ArchiveWarehouse> wrapper = new QueryWrapper<>();
        wrapper.eq(Constant.DEL_FLAG, DelFlagEnum.NORMAL.value());
        wrapper.like(StringUtils.isNotBlank(name), "name", name);
        wrapper.like(StringUtils.isNotBlank(code),"code",code);
        wrapper.eq(StringUtils.isNotBlank(warehouseId), "id", warehouseId);
        UserDetail user = SecurityUser.getUser();
        if(user.getSuperAdmin() != SuperAdminEnum.YES.value()) {
            wrapper.eq("tenant_code",user.getTenantCode());
        }
        return wrapper;
    }

    @Override
    public void delete(List<Long> ids) {
        List<ArchiveWarehouseLocation> locationList = archiveWarehouseLocationMapper.selectList(
                new QueryWrapper<ArchiveWarehouseLocation>().in("warehouse_id", ids)
        );
        if(CollectionUtils.isNotEmpty(locationList)) {
            throw new RenException("该库房下存在密集架不能删除");
        }
        this.baseDao.deleteBatchIds(ids);
    }

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public void save(ArchiveWarehouse archiveWarehouse) {
        archiveWarehouse.setCode("DN-KF-"+ IdWorker.getIdStr());
        this.baseDao.insert(archiveWarehouse);
        Long number = archiveWarehouse.getIntensiveNumber();
        String shelvingNoBeginRule = archiveWarehouse.getShelvingNoBeginRule();
        String[] split = shelvingNoBeginRule.split("-");
        UserDetail user = SecurityUser.getUser();
        for (int i = 1;i < number + 1 ; i++) {
            ArchiveWarehouseLocation location = new ArchiveWarehouseLocation();
            location.setCreator(user.getId());
            location.setTenantCode(user.getTenantCode());
            location.setCreateDate(new Date());
            location.setDelFlag(0);
            location.setWarehouseId(archiveWarehouse.getId());
            location.setLayerNo(archiveWarehouse.getLayerNo());
            location.setColumnNo(archiveWarehouse.getColumnNo());
            location.setSegmentNo(split[0]+ "-"+(Long.parseLong(split[1]) + i));
            location.setUsableCapacity(archiveWarehouse.getSignCapacity());
            archiveWarehouseLocationService.save(location);
        }

    }

    @Override
    public List<ArchiveWarehouse> selectList() {
        return this.baseDao.selectList(getWrapper(new HashMap<>()));
    }

    @Override
    public List<ArchiveWarehouseVo> simulation(Map<String, Object> params) {
        String fileNumber = (String)params.get("fileNumber");
        String segmentNo = (String)params.get("segmentNo");
        if(StringUtils.isEmpty(fileNumber)) {
            List<ArchiveBaseStore> archiveBaseStoreList = archiveBaseStoreMapper.selectList(new QueryWrapper<ArchiveBaseStore>().eq("file_number", fileNumber));
            if(CollectionUtils.isNotEmpty(archiveBaseStoreList)) {
                ArchiveWarehouseLocation location = archiveWarehouseLocationMapper.selectById(archiveBaseStoreList.get(0).getLocationId());
                params.put("warehouseId",location.getWarehouseId());
            }
        }

        if(StringUtils.isEmpty(segmentNo)) {
            List<ArchiveWarehouseLocation> warehouseLocations = archiveWarehouseLocationMapper.selectList(new QueryWrapper<ArchiveWarehouseLocation>().eq("segment_no", segmentNo));
            if((CollectionUtils.isNotEmpty(warehouseLocations))) {
                params.put("warehouseId",warehouseLocations.get(0).getWarehouseId());
            }
        }

        List<ArchiveWarehouse> archiveWarehouses = baseDao.selectList(getWrapper(params));
        List<ArchiveWarehouseVo> archiveWarehouseVoList = ConvertUtils.sourceToTarget(archiveWarehouses, ArchiveWarehouseVo.class);
        if(CollectionUtils.isNotEmpty(archiveWarehouseVoList)) {
            archiveWarehouseVoList.forEach(item->{
                List<ArchiveWarehouseLocation> locationList = archiveWarehouseLocationMapper.selectList(
                        new QueryWrapper<ArchiveWarehouseLocation>().eq("warehouse_id", item.getId()));
                if(locationList.size()>0) {
                    item.setCapacity(new BigDecimal(locationList.size()));
                }
                long notEmpty = locationList.stream().filter(i -> !i.getLocationStatus().equals("EMPTY")).count();
                item.setHasBeenUsed(new BigDecimal(notEmpty));
                if(notEmpty == 0) {
                    item.setUseRatio(BigDecimal.ZERO);
                }
                else {
                    BigDecimal bigDecimal = item.getHasBeenUsed().subtract(item.getCapacity()).setScale(2, RoundingMode.HALF_UP);
                    item.setUseRatio(bigDecimal);
                }
                List<ArchiveWarehouseZone> warehouseZoneList = archiveWarehouseZoneMapper.selectList(new QueryWrapper<ArchiveWarehouseZone>().eq("warehouse_id", item.getId()));
                if(CollectionUtils.isNotEmpty(warehouseZoneList)) {
                    List<ArchiveBaseInfo> archiveBaseInfoList = archiveBaseInfoMapper.selectBatchIds(
                            warehouseZoneList.stream().map(ArchiveWarehouseZone::getArchiveId).collect(Collectors.toList()));
                    if(CollectionUtils.isNotEmpty(archiveBaseInfoList)) {
                        String s = String.join(",", archiveBaseInfoList.stream().map(ArchiveBaseInfo::getCode).collect(Collectors.toList()));
                        item.setGeneralArchiveName(s);
                    }

                }
            });

        }
        return archiveWarehouseVoList;
    }
}
